1.2.1 react 基础写法
1.创建 React 组件
- 1.1
class Component extends React.Component
import React from 'react';
class Component extends React.Component {
//needs render function
render() {
return (
//return should tell React what the DOM should look like
//if this component is rendered in the browser
);
}
}
2
3
4
5
6
7
8
9
10
11
- 1.2 function
function Component(props) {
return (
//return should tell React what the DOM should look like
//if this component is rendered in the browser
);
}
2
3
4
5
6
2.HelloWorld
import React from 'react';
function HelloWorld(props){
//function must return something
return (
//return should tell React to render Hello World in the browser
);
// div
// <div>Hello World</div>
// jsx
// return React.createElement('div', null, 'Hello World');
}
2
3
4
5
6
7
8
9
10
11
12
13
14
- html
<table>
<thead>
<th>
<td>Col</td>
</th>
</thead>
<tbody>
<tr>
<td>Cell</td>
</tr>
</tbody>
</table>
2
3
4
5
6
7
8
9
10
11
12
- React.createElement
React.createElement('table', null,
[
React.createElement('thead', null,
React.createElement('th', null,
React.createElement('td', null, 'Col')
)
),
React.createElement('tbody', null,
React.createElement('tr', null,
React.createElement('td', 'null', 'Cell')
)
)
]
2
3
4
5
6
7
8
9
10
11
12
13
{ //javascript code }
3.JSX 中执行 js 代码: 使用 function CompanyProfile(props) {
//ticker and companyProfileInfo stored in a variable
const ticker = 'APPL';
const companyProfileInfo = {
'Company Name': 'Apple Inc.',
'Exchange': 'Nasdaq',
'Sector': 'Technology',
'Industry': 'Computer Hardware',
'CEO': 'Timothy D. Cook'
};
return (
<div>
<div>Profile of: {ticker}</div>
<div>
{
{/*This is javascript code inside the curly braces*/}
Object.keys(companyProfileInfo)
.map((key, index) => {
return <div>{key}: {companyProfileInfo[key]}</div>
})
}
</div>
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
注意:一个组件中必须只有一个根标签, 如:
return (
<div>
<div>
<div></div>
</div>
<div></div>
</div>
)
2
3
4
5
6
7
8
而不是下面这样:
# 这样写就是错误的
return (
<div></div>
<div></div>
)
2
3
4
5
4.样式写法
- 4.1 style:
## html 中
<div style="bottom-border: 1px solid green"></div>
## react JSX 中,css 属性驼峰命名
<div style={{ bottomBorder: `1px solid green`}}></div>
2
3
4
5
6
- 4.2 class
## html 中
<div class="container"></div>
## react JSX 中
<div className={"container"}></div>
2
3
4
5
- 4.2.1 多个 class 判断
使用一个小工具 classNames:
使用方法:
import classnames from 'classnames';
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
2
3
4
5
6
7
8
9
4.3 Event
## html 中
<div onclick="clickHandler()"></div>
## react JSX 中
div onClick={function(){ alert('clicked')}}>
function ClickableButton(props){
//callback function that's called when button is clicked
const handleClick = () => { alert('Clicked') }
return (
<button onClick={handleClick}></button>
)
}
# Function Binding
class Input extends React.Component {
constructor(props){
super(props);
//bind handleChange function to proper this
this.handleChange = this.handleChange.bind(this);
}
handleChange(e){
this.setState({
inputValue: e.target.value
});
}
render(){
return(
<input onChange={this.handleChange} value={this.state.inputValue}/>
)
}
}
# react 向事件处理程序传递参数
<button onClick={this.editRow.bind(this, id)}>Delete Row</button>
editRow(id, e) {
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
5. Props (单向)
父子组件传参数 props, 子组件不能修改 props 中参数
function Children(props) {
return (
<div>{props.textToDisplay}</div>
)
}
function Parent(props) {
return (
<Children textToDisplay={'Hello'}></Children>
)
}
2
3
4
5
6
7
8
9
10
11
在多数情况下,组件最好明确定义一个 props 可以接受的数据类型,数据结构,
prop-types: facebook/prop-types
.isRequired: 如果
PropTypes.string.isRequired,
那就是必选的;如果PropTypes.string
,那就是可选的;defaultProps: 通过赋值特定的 defaultProps 属性为 props 定义默认值
// 任何东西都可以被渲染:numbers, strings, elements,或者是包含这些类型的数组(或者是片段)。 optionalNode: PropTypes.node, // 一个 React 元素。 optionalElement: PropTypes.element, // 你也可以声明一个 prop 是类的一个实例。 // 使用 JS 的 instanceof 运算符。 optionalMessage: PropTypes.instanceOf(Message), // 你可以声明 prop 是特定的值,类似于枚举 optionalEnum: PropTypes.oneOf(['News', 'Photos']), // 一个对象可以是多种类型其中之一 optionalUnion: PropTypes.oneOfType([ PropTypes.string, PropTypes.number, PropTypes.instanceOf(Message) ]), // 一个某种类型的数组 optionalArrayOf: PropTypes.arrayOf(PropTypes.number), // 属性值为某种类型的对象 optionalObjectOf: PropTypes.objectOf(PropTypes.number), // 一个特定形式的对象 optionalObjectWithShape: PropTypes.shape({ color: PropTypes.string, fontSize: PropTypes.number }),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
使用 :
# 安装
yarn add prop-types
# 使用
import React from 'react';
import PropTypes from 'prop-types';
class SoftwareEngineer extends React.Component {
render(){
return (...)
}
}
//defines "propTypes" property in this component
SoftwareEngineer.propTypes = {
name: PropTypes.string.isRequired, //expects string and is required
hobbies: PropTypes.arrayOf(PropTypes.string), //expects array of string
address: PropTypes.shape({
street: PropTypes.string,
city: PropTypes.string
}) //must be an object with 'street' and 'city' fields
}
# 指定 props 的默认值:
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
// 指定 props 的默认值:
Greeting.defaultProps = {
name: 'Stranger'
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
6.state: 组件本身的状态,不和组件的父级或者子级共享
state 只是一个对象
class Component extends React.Component {
constructor(props){
super(props);
this.state = {
counter: 0
}
}
render() {
return <div>{this.state.counter}</div>
}
}
{
Object.keys(companyProfileInfo)
.map((key, index) => {
return <div>{key}: {companyProfileInfo[key]}</div>
})
}
</div>
)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 6.1 状态更新,必须使用
setState
当 state 发生变化时,React 会重新渲染你的组件,
setState 函数的是异步的
this.setState({
counter: 2
});
2
3
为什么setState是异步的?有人再react官网上提过了的issue,Dan Abramov的回复:
保证内部的一致性,因为更新props的机制可以理解成异步的,那么更新state的机制也要理解成异步的
在许多情况下setState()重新渲染的同步效率很低,而异步可以将几个state合并执行,提高效率。
可以利用异步的特性处理很多事情,如果在开始的页面设了一些异步操作,
然后去跳了路由换了页面,那么原先的页面即使不展示了,还会继续执行那些异步的东西。6.2 使用当前的 state 值去更新 state,
//If you are using current state value to update the state, always use updater function
console.log(this.state.counter); //prints 0
this.setState((state) => ({ counter: state.counter + 1}) );
this.setState((state) => ({ counter: state.counter + 1}) );
this.setState((state) => ({ counter: state.counter + 1}) );
2
3
4
5
state 和 props 主要的区别在于: props 是不可变的,而 state 可以根据与用户交互来改变
7.生命周期方法
哪种方式定义的组件,其组件名都必须是大写
1.componentDidMount 是进行网络调用的正确生命周期方法(使用API获取数据),当组件挂载在DOM上时 componentDidMount 只调用一次; 2.可以使用 componentDidUpdate,每次更新组件时都会调用此生命周期方法; 版本17.0的一部分弃用,因此请勿使用它们
componentWillMount
componentWillUpdate
componentWillReceiveProps
2
3
demo:
class ComponentWithLifecycle extends React.Component {
constructor(props){
super(props);
}
componentDidMount(){
//This will be called after the component is mounted to the DOM
}
componentDidUpdate(prevProps, prevState){
//This will be called after the component is updated
//Remember component can only be updated when the state changes
//or the props changes
}
componentWillUnmount(){
//This will be called right before this component is unmounted from
//the DOM
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20